package com.moweilin.mo_utils.cli;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameters;

import java.util.*;

/**
 * Created by moweilin on 2017/2/15.
 */
public class CommandFactory {
    private JCommander commander;
    private Class mainClass;
    private String defaultCommand;
//    private List<Class> commandList;
    private ResourceBundle resourceBundle;
    private Map<Class,CommandHandler> commandHandlerMap;
    public CommandFactory(Class mainClass){
        this(mainClass,"com.moweilin.mo_utils.cli.DefaultResource");
    }
    public CommandFactory(Class mainClass,String resource){
        this(mainClass,resource,HelpCommand.NAME);
    }
    public CommandFactory(Class mainClass,String resource,String defaultCommand){
        this.mainClass = mainClass;
        this.defaultCommand = defaultCommand;
//        this.commandList = new ArrayList<>();
        this.resourceBundle = ResourceBundle.getBundle(resource);
        this.commandHandlerMap = new HashMap<>();
        register(HelpCommand.class,this::helpHandler);
        register(VersionCommand.class,this::versionHandler);
    }

    public void setDefaultCommand(String defaultCommand) {
        this.defaultCommand = defaultCommand;
    }



    protected void helpHandler(HelpCommand cmd){
        cmd.execute(commander);
    }
    protected void versionHandler(VersionCommand cmd){
        System.out.println("version todo");
    }

    public <T> void register(Class<T> commandClass,CommandHandler<T> handler){
        if(commandHandlerMap.containsKey(commandClass)){
            throw new RuntimeException(commandClass.getName() + " already exists.");
        }
        commandHandlerMap.put(commandClass,handler);
    }
    private void initCommander(){
        commander = new JCommander();
        commander.setDescriptionsBundle(resourceBundle);
        commandHandlerMap.keySet().forEach(commandClass -> {
            try {
                Object command = commandClass.newInstance();
                commander.addCommand(command);
            } catch (Exception e){
                throw new RuntimeException(e);
            }
        });
    }
    private void clearCommander(){
        commander = null;
    }

    public void run(String ... args){
        initCommander();
        commander.parse(args);
        String pc = commander.getParsedCommand();
        if(pc == null || pc.isEmpty()){
            runDefault();
        }else {
            executeCmd(pc);
        }
        clearCommander();
    }
    private void runDefault(){
        run(defaultCommand);
    }
    @SuppressWarnings("unchecked")
    private void executeCmd(String cmd){
        JCommander jcmd = commander.getCommands().get(cmd);
        List<Object> cmdList = jcmd.getObjects();
        if(cmdList != null && cmdList.size() > 0){
            Object cmdObject = cmdList.get(0);
            CommandHandler handler = commandHandlerMap.get(cmdObject.getClass());
            handler.handle(cmdObject);
        }
    }

}

